// 表单验证
define(function(require, exports, module) {
	var $ = require('bigfoot/common');

    module.exports = {
    	init : function(){
    		if(!this.formEl)throw '未设置表单元素！';

    		// 提示
    		var tipsMsgs = this.formEl.queryChild('*[tipsMsg]')(function(tipsMsg){
    			if(tipsMsg.tagName == 'DD' || tipsMsg.tagName == 'SPAN'){
	    			// 非 input 元素，没有 焦点事件，用鼠标移入、移出代替。
	    			tipsMsg.on('mouseover', tipsMsg_onFocus);
	    			tipsMsg.on('mouseout', tipsMsg_onBlur);
    			}else{
	    			tipsMsg.on('focus', tipsMsg_onFocus);
	    			tipsMsg.on('blur', tipsMsg_onBlur);
    			}
    		});


    		if (!tipsMsgs || !tipsMsgs.length)console.warn('一个要检测的字段都没有？');

    		// 错误的
    		var errMsgs = this.formEl.queryChild('input[requiredField], input[requiredSize], input[regexpCheck]')(function(errMsg){
    			errMsg.on('blur', errMsg_onBlur);
    		});

    		if (errMsgs)this.fieldsToCheck = errMsgs; // 要在表单提交之前的那些字段
    		else console.warn('没有要提示的错误字段？');    
    	},
    	checkAllFields : function(){
    		var isAllPassed = true;
    		var errMsgs = '', markedFirstError = false;

    		for(var fieldState, i = 0, j = this.fieldsToCheck.length; i < j; i++){
    			fieldState = errMsg_onBlur({ 
    				target : this.fieldsToCheck[i], 
    				isNotShowMsgBox : false
    			});
    			
    			if (fieldState.isAllPassed === false){
    				isAllPassed = false; // 一有错，就不能提交
    				errMsgs += 	fieldState.errMsg + '\n';
    				
    				// 对第一个出现错误的元素，进行标记，获得焦点
    				if(markedFirstError === false){
    					this.fieldsToCheck[i].focus();
    					markedFirstError = true;
    				}
    			}
    		}

    		// !isAllPassed && alert('提交表单失败，错误原因如下：\n' + errMsgs);

    		return isAllPassed;
    	}
    };
    // 相对于 表单的坐标
    function getXY2form(el){
		var x = 0, y = 0;
		var _el = el;
		// debugger
		while (el != null) {
			if(el.tagName == 'FORM')break;
		    x += el.offsetLeft;
		    y += el.offsetTop;
		    el = el.offsetParent;
		}
		// 如果在 fixed 布局中，要为垂直方向加上 document.documentElement.scrollTop
		// 优化：考虑使用 offsetParant
		while(_el && _el != document/*如果要查询到 doc，性能上会不会伤不起啊？*/){
			if(getComputedStyle(_el).position == 'fixed'){
				y += document.documentElement.scrollTop;
				break;
			}
			_el = _el.parentNode;
		}

    	return {
    		x : x, y : y
    	};
    }

    // 显示提示/警告组件
    function show(boxEl, inputEl, textStr){
		if(!boxEl || window.getComputedStyle(boxEl).position != 'absolute'){
			throw '对话框元素不存在或未设置样式！';
		}
    	var xy = getXY2form(inputEl);
    	
    	boxEl.updateChild('.text', textStr);

		// debugger
		boxEl.style.top  = (xy.y - 40) + 'px';
		boxEl.style.left = xy.x + 'px';
		boxEl.removeCls('hide');
    }

    function tipsMsg_onFocus(e){
		var boxEl = document.querySelector('.tipsMsg_Box'),
			input = e.currentTarget, // 要求为登记事件的那个元素 
			tipsMsg_text = input.getAttribute('tipsMsg') || '请输入字段';

		show(boxEl, input, tipsMsg_text);
    }

    function tipsMsg_onBlur(e){
		var tipsMsg_Box = document.querySelector('.tipsMsg_Box');
		tipsMsg_Box && tipsMsg_Box.addCls('hide');
    }

	function showErrMsgBox(input, errMsg){
// debugger
		var errMsg_Box = document.querySelector('.errMsg_Box');
		show(errMsg_Box, input, errMsg);

		window.setTimeout(function(){errMsg_Box.addCls('hide');}, 2000);
		
		input.parentNode.addCls('errState');

		// 错误状态的图标
//		var disallowIcon = $.call(input.parentNode, '.disallowStateIcon');
//		if(!disallowIcon){
//			disallowIcon = document.createElement("div");
//			disallowIcon.className = 'disallowStateIcon';
//			// debugger;
//			disallowIcon.style.left = input.offsetWidth - 18 + 'px'; // 与输入框右端对齐
//			input.parentNode.appendChild(disallowIcon);
//		}
	}

	function errMsg_onFocus(e){
		// var errMsg_Box = $('.errMsg_Box');
		// errMsg_Box.addCls('hide');
	}
	// 获取字段 名称 和 错误原因
	function getFieldInfo(input, errMsg){
		var dd = input.parentNode;
		dd.addCls('errState');
		var dt = dd.previousSibling; // 少一次循环
		while(dt){
			if(dt.tagName == 'DT')break;
			dt = dt.previousSibling;
		}
		var fieldName = dt.innerHTML.replace(/<.*>|\s/g, ''); // 删除子标签和空格，只保留文本节点
		// debugger;
		return fieldName + errMsg;
	}
	function errMsg_onBlur(e){
		var input = e.target, isNotShowMsgBox = e.isNotShowMsgBox;
		var	errMsg, // 错误原因
			fieldState = {isAllPassed : true}; 
		
		if (input.hasAttribute('requiredField') && !trim(input.value)){
			
			errMsg = input.getAttribute('errMsg') || '该项必填！'
			if(isNotShowMsgBox)
				fieldState.errMsg = getFieldInfo(input, errMsg);
			else showErrMsgBox(input, errMsg);
		
		}else if(input.hasAttribute('requiredSize') && trim(input.value).length < Number(input.getAttribute('requiredSize'))){
			
			errMsg = '该项长度太小，须{0}个字符以上'.format(input.getAttribute('requiredSize'));
			if(isNotShowMsgBox)
				fieldState.errMsg = getFieldInfo(input, errMsg);
			else showErrMsgBox(input, errMsg);
		
		}else if(input.hasAttribute('regexpCheck') && input.hasAttribute('requiredField')){
			if(!checkByRegExp(input)){
				// debugger
				errMsg = input.hasAttribute('errMsg') ? input.getAttribute('errMsg') : '不符合格式！';

				if(isNotShowMsgBox)
					fieldState.errMsg = getFieldInfo(input, errMsg);
				else showErrMsgBox(input, errMsg);
			}else{
				// 通过验证
				input.parentNode.removeCls('errState');
				return fieldState;
			}

		}else if(input.hasAttribute('regexpCheck') && !input.hasAttribute('requiredField')){
			// JUST Check
			if(input.value){
				//	填了，帮他检查一下。如果不通过，还是不能提交表单
				if(!checkByRegExp(input)){
					errMsg = input.hasAttribute('errMsg') ? input.getAttribute('errMsg') : '不符合格式！';
					if(isNotShowMsgBox)
						fieldState.errMsg = getFieldInfo(input, errMsg);
					else showErrMsgBox(input, errMsg);
				}else{
					// 填了，也通过了，尽管可以不填
					input.parentNode.removeCls('errState');
					return fieldState;					
				}
			
			}else{
				// 不是必填，也就是无须检查，返回 true 通过
				input.parentNode.removeCls('errState');
				return fieldState;
			}
		}else{
			input.parentNode.removeCls('errState');
			return fieldState;
		}

		fieldState.isAllPassed = false; // 不通过
		return fieldState;
	}

	function checkByRegExp(input){
		var regexpCheck = input.getAttribute('regexpCheck');
		switch(regexpCheck){
			case 'email':
			case 'url':
				regexpCheck = validatorReg[regexpCheck];
			break;
			default:
				regexpCheck = new RegExp(regexpCheck);
		}

		return regexpCheck.test(input.value);
	}

	function trim(str){
		return str.replace(/^\s+|\s+$/g, '');
	};
	var validatorReg = {
		require : /.+/,
		email : /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
		url : /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/,
		Integer : /^[-\+]?\d+$/,
		Double : /^[-\+]?\d+(\.\d+)?$/,
		English : /^[A-Za-z]+$/,
		Chinese : /^[\u0391-\uFFE5]+$/
	}
});